package com.company.pangu.aliyun.live.client;

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.live.model.v20161101.DescribeLiveStreamsOnlineListRequest;
import com.aliyuncs.live.model.v20161101.DescribeLiveStreamsOnlineListResponse;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.company.pangu.aliyun.live.config.LiveConfig;
import com.company.pangu.aliyun.live.enums.LiveStreamType;
import com.company.pangu.aliyun.live.enums.StreamBitRateType;
import com.company.pangu.aliyun.live.request.*;
import com.company.pangu.aliyun.live.response.*;
import com.company.pangu.aliyun.live.util.LiveStreamUtils;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>LIVE SDK CLIENT</p >
 *
 * @author youyoukele
 * @version 1.0
 * @date 2021/10/27 14:42
 */
@Slf4j
public class LiveClient {

    private final LiveConfig liveConfig;

    private final IAcsClient liveAcsClient;

    public LiveClient(LiveConfig liveConfig) {
        this.liveConfig = liveConfig;
        String regionId = liveConfig.getRegionId();
        String accessKeyId = liveConfig.getAccessKeyId();
        String accessKeySecret = liveConfig.getAccessKeySecret();

        String endPoint = "live.aliyuncs.com";
        DefaultProfile.addEndpoint(regionId,"live",endPoint);

        IClientProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret);
        liveAcsClient = new DefaultAcsClient(profile);
    }
//
//    public static void main(String[] args) {
//        LiveConfig liveConfig = LiveConfig.builder()
//                .accessKeySecret("YJ6PXGinBfgya9yUZnP35ohbJIbmna")
//                .accessKeyId("LTAI4G5LauFqZSn7vmyr6Nwf")
//                .appName("oversea")
//                .expireTime(86400L)
//                .pullDomain("pull-live.abcd.vip")
//                .pushDomain("push-live.abcd.vip")
//                .pushKey("i5FNPUrpg7")
//                .pullKey("GM9GefVSJV")
//                .regionId("cn-shanghai")
//                .build();
//        LiveClient liveClient = new LiveClient(liveConfig);
//        ForbidLiveStreamRequest request = new ForbidLiveStreamRequest();
//        request.setStreamName("1455433276071092224_1458353260766183424");
//        ForbidLiveStreamResponse response = liveClient.forbidLiveStream(request);
//        System.out.println(JSONUtil.toJsonPrettyStr(response));
//    }

    /**
     * 构建直播渠道（推拉流信息）
     *
     * @param request
     * @return
     */
    public BuildLiveChannelResponse buildLiveChannel(BuildLiveChannelRequest request) {
        List<StreamBitRateType> streamTypes = request.getStreamTypes();
        String streamName = request.getStreamName();

        // 获取推流信息
        String pushUrl = LiveStreamUtils.buildPushUrl(liveConfig, streamName);
        // 获取拉流信息
        List<BuildLiveChannelResponse.PullUrl> livePullInfoUrls = LiveStreamUtils.buildPullUrl(liveConfig, streamName, streamTypes);

        return BuildLiveChannelResponse.builder()
                .pullUrls(livePullInfoUrls)
                .pushUrl(pushUrl)
                .build();
    }

    /**
     * 禁止直播流
     * <p>
     * 调用ForbidLiveStream禁止某条流的推送，可以预设某个时刻将流恢复。
     * <p>
     * 说明 禁止直播流的上限为10,000路，超出限制将禁用失败，请您注意统计当前禁用流的数量。调用频率限制为20次/秒。
     * <p>
     * https://help.aliyun.com/document_detail/35413.html
     *
     * @param request
     * @return
     */
    public ForbidLiveStreamResponse forbidLiveStream(ForbidLiveStreamRequest request) {
        com.aliyuncs.live.model.v20161101.ForbidLiveStreamRequest forbidLiveStreamRequest = new com.aliyuncs.live.model.v20161101.ForbidLiveStreamRequest();
        forbidLiveStreamRequest.setDomainName(liveConfig.getPushDomain());
        forbidLiveStreamRequest.setAppName(liveConfig.getAppName());
        forbidLiveStreamRequest.setStreamName(request.getStreamName());
        forbidLiveStreamRequest.setLiveStreamType(LiveStreamType.PUBLISHER.getCode());
        try {
            com.aliyuncs.live.model.v20161101.ForbidLiveStreamResponse forbidLiveStreamResponse = liveAcsClient.getAcsResponse(forbidLiveStreamRequest);
            return ForbidLiveStreamResponse.builder()
                    .requestId(forbidLiveStreamResponse.getRequestId())
                    .build();
        } catch (ClientException e) {
            log.error("forbidLiveStream has error", e);
            throw new RuntimeException("invoke live sdk error");
        }
    }

    /**
     * 恢复直播流
     * <p>
     * https://help.aliyun.com/document_detail/35414.html
     *
     * @param request
     * @return
     */
    public ResumeLiveStreamResponse resumeLiveStream(ResumeLiveStreamRequest request) {
        com.aliyuncs.live.model.v20161101.ResumeLiveStreamRequest resumeLiveStreamRequest = new com.aliyuncs.live.model.v20161101.ResumeLiveStreamRequest();
        resumeLiveStreamRequest.setDomainName(liveConfig.getPushDomain());
        resumeLiveStreamRequest.setAppName(liveConfig.getAppName());
        resumeLiveStreamRequest.setStreamName(request.getStreamName());
        resumeLiveStreamRequest.setLiveStreamType(LiveStreamType.PUBLISHER.getCode());
        try {
            com.aliyuncs.live.model.v20161101.ResumeLiveStreamResponse resumeLiveStreamResponse = liveAcsClient.getAcsResponse(resumeLiveStreamRequest);
            return ResumeLiveStreamResponse.builder()
                    .requestId(resumeLiveStreamResponse.getRequestId())
                    .build();
        } catch (ClientException e) {
            log.error("resumeLiveStream has error", e);
            throw new RuntimeException("invoke live sdk error");
        }
    }

    /**
     * 查询单路流状态
     * <p>
     * https://help.aliyun.com/document_detail/315391.html
     *
     * @param request
     * @return
     */
    public DescribeLiveStreamStateResponse describeLiveStreamState(DescribeLiveStreamStateRequest request) {
        com.aliyuncs.live.model.v20161101.DescribeLiveStreamStateRequest describeLiveStreamStateRequest = new com.aliyuncs.live.model.v20161101.DescribeLiveStreamStateRequest();
        describeLiveStreamStateRequest.setDomainName(liveConfig.getPushDomain());
        describeLiveStreamStateRequest.setAppName(liveConfig.getAppName());
        describeLiveStreamStateRequest.setStreamName(request.getStreamName());
        try {
            com.aliyuncs.live.model.v20161101.DescribeLiveStreamStateResponse describeLiveStreamStateResponse = liveAcsClient.getAcsResponse(describeLiveStreamStateRequest);

            return DescribeLiveStreamStateResponse.builder()
                    .requestId(describeLiveStreamStateResponse.getRequestId())
                    .streamState(describeLiveStreamStateResponse.getStreamState())
                    .type(describeLiveStreamStateResponse.getType())
                    .build();
        } catch (ClientException e) {
            log.error("describeLiveStreamState has error", e);
            throw new RuntimeException("invoke live sdk error");
        }
    }

    /**
     * 查询域名在线流列表
     * <p>
     * https://help.aliyun.com/document_detail/35409.html
     *
     * @param request
     * @return
     */
    public DescribeAllLiveStreamInfoResponse describeLiveStreamsOnlineList(DescribeAllLiveStreamInfoRequest request) {
        DescribeLiveStreamsOnlineListRequest describeLiveStreamsOnlineListRequest = new DescribeLiveStreamsOnlineListRequest();
        describeLiveStreamsOnlineListRequest.setDomainName(liveConfig.getPushDomain());
        describeLiveStreamsOnlineListRequest.setAppName(liveConfig.getAppName());
        describeLiveStreamsOnlineListRequest.setPageSize(request.getPageSize());
        // 查询原始流
        describeLiveStreamsOnlineListRequest.setStreamType("raw");
        // 精准匹配
        describeLiveStreamsOnlineListRequest.setQueryType("strict");
        try {
            DescribeLiveStreamsOnlineListResponse describeLiveStreamsOnlineListResponse = liveAcsClient.getAcsResponse(describeLiveStreamsOnlineListRequest);
            List<String> streamNames = describeLiveStreamsOnlineListResponse.getOnlineInfo()
                    .stream()
                    .map(DescribeLiveStreamsOnlineListResponse.LiveStreamOnlineInfo::getStreamName)
                    .collect(Collectors.toList());
            return DescribeAllLiveStreamInfoResponse.builder()
                    .pageNum(describeLiveStreamsOnlineListResponse.getPageNum())
                    .pageSize(describeLiveStreamsOnlineListResponse.getPageSize())
                    .totalPage(describeLiveStreamsOnlineListResponse.getTotalPage())
                    .streamNames(streamNames)
                    .totalNum(describeLiveStreamsOnlineListResponse.getTotalNum())
                    .build();
        } catch (ClientException e) {
            log.error("describeLiveStreamsOnlineList has error", e);
            throw new RuntimeException("invoke live sdk error");
        }
    }

    /**
     * shut down
     */
    public void shutdown() {
        if (Objects.nonNull(liveAcsClient)) {
            this.liveAcsClient.shutdown();
        }
    }

}
